package com.ruyuan.eshop.order.mq.listener;

import com.alibaba.fastjson.JSONObject;
import com.ruyuan.eshop.common.constants.RedisLockKeyConstants;
import com.ruyuan.eshop.common.core.BeanCopierUtil;
import com.ruyuan.eshop.common.enums.OrderStatusChangeEnum;
import com.ruyuan.eshop.common.exception.BaseBizException;
import com.ruyuan.eshop.common.message.OrderEvent;
import com.ruyuan.eshop.common.redis.RedisLock;
import com.ruyuan.eshop.common.utils.JsonUtil;
import com.ruyuan.eshop.fulfill.domain.event.OrderDeliveredWmsEvent;
import com.ruyuan.eshop.fulfill.domain.event.OrderOutStockWmsEvent;
import com.ruyuan.eshop.fulfill.domain.event.OrderSignedWmsEvent;
import com.ruyuan.eshop.order.domain.dto.WmsShipDTO;
import com.ruyuan.eshop.order.exception.OrderErrorCodeEnum;
import com.ruyuan.eshop.order.service.OrderFulFillService;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.client.consumer.listener.ConsumeOrderlyContext;
import org.apache.rocketmq.client.consumer.listener.ConsumeOrderlyStatus;
import org.apache.rocketmq.client.consumer.listener.MessageListenerOrderly;
import org.apache.rocketmq.common.message.MessageExt;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * @author lxg
 * @Description: 监听物流配送结果的信息
 * @date 2022/4/821:24
 */
@Component
@Slf4j
public class OrderWmsShipResultListener implements MessageListenerOrderly {
    @Autowired
    private RedisLock redisLock;
    @Autowired
    private OrderFulFillService orderFulFillService;

    private WmsShipDTO buildWmsShip(OrderEvent orderEvent) {
        String messageContent= JSONObject.toJSONString(orderEvent.getMessageContent());
        WmsShipDTO wmsShipDTO=new WmsShipDTO();
        wmsShipDTO.setStatusChange(orderEvent.getOrderStatusChange());
        if (OrderStatusChangeEnum.ORDER_OUT_STOCKED.equals(orderEvent.getOrderStatusChange())){
            //订单出库消息
            OrderOutStockWmsEvent event=JSONObject.parseObject(messageContent,OrderOutStockWmsEvent.class);
            BeanCopierUtil.copyProperties(event, wmsShipDTO);
        }else if(OrderStatusChangeEnum.ORDER_DELIVERED.equals(orderEvent.getOrderStatusChange())){
            //订单配送消息
            OrderDeliveredWmsEvent event=JSONObject.parseObject(messageContent,OrderDeliveredWmsEvent.class);
            BeanCopierUtil.copyProperties(event, wmsShipDTO);
        }else if (OrderStatusChangeEnum.ORDER_SIGNED.equals(orderEvent.getOrderStatusChange())){
            //订单签收消息
            OrderSignedWmsEvent event = JSONObject.parseObject(messageContent,OrderSignedWmsEvent.class);
            BeanCopierUtil.copyProperties(event, wmsShipDTO);
        }
        return wmsShipDTO;
    }

    @Override
    public ConsumeOrderlyStatus consumeMessage(List<MessageExt> list, ConsumeOrderlyContext consumeOrderlyContext) {
        OrderEvent orderEvent;
        try {
            for (MessageExt messageExt : list) {
                String message = new String(messageExt.getBody());
                log.info("received orderWmsShopResult  message:{}", message);
                orderEvent= JsonUtil.json2Object(message, OrderEvent.class);
                //1、解析消息
                WmsShipDTO wmsShipDTO = buildWmsShip(orderEvent);
                //2、加分布式锁+里面的前置状态校验防止消息重复消费
                String key= RedisLockKeyConstants.ORDER_WMS_RESULT_KEY+wmsShipDTO.getOrderId();
                boolean lock=redisLock.lock(key);
                if (!lock){
                    log.error("order has not acquired lock，cannot inform order wms result, orderId={}",wmsShipDTO.getOrderId());
                    throw new BaseBizException(OrderErrorCodeEnum.ORDER_NOT_ALLOW_INFORM_WMS_RESULT);
                }
                try {
                    orderFulFillService.informOrderWmsShipResult(wmsShipDTO);
                }finally {
                    if (lock){
                        redisLock.unlock(key);
                    }
                }
            }
            return ConsumeOrderlyStatus.SUCCESS;
        }catch (Exception e){
            //处理业务逻辑失败！ Suspend current queue a moment
            log.error("consume wmsship message exception,", e);
            return ConsumeOrderlyStatus.SUSPEND_CURRENT_QUEUE_A_MOMENT;
        }

    }
}
